package xj.toolkit.netty.initializer;

import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.traffic.TrafficCounterExt;
import io.netty.util.internal.logging.InternalLoggerFactory;
import io.netty.util.internal.logging.Slf4JLoggerFactory;
import xj.toolkit.netty.handler.CloseOnIdleHandler;

/**
 * 提供日志功能和统计功能
 */
public abstract class BaseInitializer extends ChannelInitializer {
	// 放在最顶上，以让NETTY默认使用SLF4J
	static {
		if (!(InternalLoggerFactory.getDefaultFactory() instanceof Slf4JLoggerFactory)) {
			InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory());
		}
	}

	private static final Logger logger = LoggerFactory.getLogger(BaseInitializer.class);
	private TrafficCounterExt trafficCounter;

	private boolean logByteStream;
	private boolean logMessage = true;
	private int idleTimeSeconds = 0; // in seconds

	private String msgByteStreamLogName = null;

	@Override
	public void initChannel(Channel ch) throws Exception {
		LoggingHandler loggingHandler = null;
		if (logByteStream || logMessage) {
			if (StringUtils.isNoneBlank(msgByteStreamLogName)) {
				loggingHandler = new LoggingHandler(msgByteStreamLogName);
			} else {
				loggingHandler = new LoggingHandler();
			}
		}

		ChannelPipeline pipeline = ch.pipeline();
		if (logByteStream && loggingHandler != null) {
			logger.debug("ByteLogger enabled");
			pipeline.addLast("byteLogger", loggingHandler);
		}
		if (idleTimeSeconds > 0) {
			pipeline.addLast("idleHandler",
					new CloseOnIdleHandler(idleTimeSeconds, idleTimeSeconds, idleTimeSeconds, TimeUnit.SECONDS));
		}
		if (trafficCounter != null) {
			pipeline.addLast("globalByteTrafficMonitor", trafficCounter.getByteTrafficMonitor());
		}

		addCodecHandler(pipeline);
		if (trafficCounter != null) {
			pipeline.addLast("globalMessageTrafficMonitor", trafficCounter.getMessageTrafficMonitor());
		}
		if (logMessage && loggingHandler != null) {
			logger.debug("MessageLogger enabled");
			pipeline.addLast("messageLogger", loggingHandler);
		}
		addBusinessHandler(pipeline);
	}

	/**
	 * 增加编解码handler
	 *
	 * @param pipeline
	 * @throws Exception
	 */
	protected abstract void addCodecHandler(ChannelPipeline pipeline) throws Exception;

	/**
	 * 增加负责处理具体业务逻辑的handler
	 *
	 * @param pipeline
	 * @throws Exception
	 */
	protected abstract void addBusinessHandler(ChannelPipeline pipeline) throws Exception;

	/**
	 * 是否提供记录二进制日志功能
	 *
	 * @param logByteStream
	 */
	public void setLogByteStream(boolean logByteStream) {
		this.logByteStream = logByteStream;
	}

	/**
	 * 是否提供记录解码后的数据包日志功能
	 *
	 * @param logMessage
	 */
	public void setLogMessage(boolean logMessage) {
		this.logMessage = logMessage;
	}

	public void setMsgByteStreamLogName(String msgByteStreamLogName) {
		this.msgByteStreamLogName = msgByteStreamLogName;
	}

	public TrafficCounterExt getTrafficCounter() {
		return trafficCounter;
	}

	public void setTrafficCounter(TrafficCounterExt trafficCounter) {
		this.trafficCounter = trafficCounter;
	}

	public int getIdleTimeSeconds() {
		return idleTimeSeconds;
	}

	/**
	 * 最大连接空闲时间，如果设置的值大于0，则空闲该时间后将关闭连接
	 *
	 * @param idleTimeSeconds
	 *            单位 秒
	 */
	public void setIdleTimeSeconds(int idleTimeSeconds) {
		this.idleTimeSeconds = idleTimeSeconds;
	}
}
